package api

import (
	"github.com/chicken-team-outside/chicken_transmission/proxy_server/middleware"
	"github.com/chicken-team-outside/chicken_transmission/proxy_server/model"
	rpc_service "github.com/chicken-team-outside/chicken_transmission/proxy_server/rpc"
	"github.com/chicken-team-outside/chicken_transmission/proxy_server/utils"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

func initTransport(group *gin.RouterGroup) {
	group.POST("/replace", middleware.AuthWare, replaceTransport)
	group.GET("/list", middleware.AuthWare, listTransports)
	group.DELETE("/delete/:token", middleware.AuthWare, deleteTransport)
}

func replaceTransport(ctx *gin.Context) {
	userId, ok := middleware.GetUserId(ctx)
	if !ok {
		utils.BadRequest(ctx, "token is invalid!")
		return
	}
	query := &model.TransportInfo{}
	err := ctx.ShouldBindJSON(query)
	if err != nil {
		zap.L().Info("can't bind query", zap.Error(err))
		utils.BadRequest(ctx, "bad parameters!")
		return
	}
	if query.Token != "" {
		if _, err = uuid.Parse(query.Token); err != nil {
			utils.BadRequest(ctx, "invalid token!")
			return
		}
		if !query.IsActive {
			info, _ := model.GetTransportInfoByTokenOrId(query.Token, 0)
			if info != nil {
				query.Id = info.Id
			}
		}
	} else {
		query.Token = uuid.NewString()
	}
	query.UserId = userId
	err = model.ReplaceTransportInfo(query)
	if err != nil {
		zap.L().Error("can't replace transport info", zap.Error(err), zap.String("token", query.Token), utils.UnknownError(ctx))
		return
	}
	if !query.IsActive {
		rpc_service.CloseClient(query.Id)
	}
	utils.Success(ctx, "success", gin.H{
		"token": query.Token,
	})
}

type listTransportItem struct {
	*model.TransportInfo
	Online bool `json:"online"`
}

func listTransports(ctx *gin.Context) {
	userId, ok := middleware.GetUserId(ctx)
	if !ok {
		utils.BadRequest(ctx, "token is invalid!")
		return
	}
	info, err := model.GetUserTransportInfos(userId)
	if err != nil {
		zap.L().Error("can't get transport info", zap.Error(err), zap.Uint64("id", userId), utils.UnknownError(ctx))
	} else {
		results := make([]*listTransportItem, len(info))
		for i, item := range info {
			results[i] = &listTransportItem{
				TransportInfo: item,
				Online:        rpc_service.GetClient(item.Id) != nil,
			}
		}
		utils.Success(ctx, "success", results)
	}
}

func deleteTransport(ctx *gin.Context) {
	token := ctx.Param("token")
	if _, err := uuid.Parse(token); err != nil {
		utils.BadRequest(ctx, "token is invalid!")
		return
	}
	userId, ok := middleware.GetUserId(ctx)
	if !ok {
		utils.BadRequest(ctx, "token is invalid!")
		return
	}
	info, err := model.GetTransportInfoByTokenOrId(token, 0)
	if err != nil {
		zap.L().Error("can't get transport info", zap.Error(err), zap.String("token", token), utils.UnknownError(ctx))
		return
	}
	if info == nil || userId != info.UserId {
		utils.BadRequest(ctx, "no such transport!")
		return
	}
	err = rpc_service.DeleteTransport(userId, token)
	if err != nil {
		zap.L().Error("can't delete transport", zap.Error(err), zap.String("token", token), utils.UnknownError(ctx))
		return
	}
	utils.Success(ctx, "success", gin.H{
		"token": token,
	})
}
